#ifndef _ENUMARRAY_H
#define _ENUMARRAY_H
#include <array>
#include <stdexcept>
#include <utility>

template< typename Enum, typename _Ty >
    requires std::is_enum_v<Enum> && requires(Enum e) { Enum::Max; }
class EnumArray {
private:
    std::array<_Ty, size_t(Enum::Max)> data;
public: 
    using _Enum = Enum;
    template<typename... Args>
    EnumArray(Args&&... args) : data{ std::forward<Args>(args)... } {};
    EnumArray() = default;

    _Ty& operator[](typename Enum index) noexcept {
        return data[size_t(index)];
    };
    const _Ty& operator[](typename Enum index) const noexcept {
        return data[size_t(index)];
    };

    _Ty& at(typename Enum index){
        if (size_t(index) < 0 || size_t(index) >= size_t(Enum::Max)){
            throw std::out_of_range("Enum out of range");
        }
        return data[size_t(index)];
    };
    const _Ty& at(typename Enum index) const{
    if (size_t(index) < 0 || size_t(index) >= size_t(Enum::Max)){
        throw std::out_of_range("Enum out of range");
    }
    return data[size_t(index)];
};
    
    auto begin(){
        return data.begin();
    };
    
    auto cbegin(){
        return data.cbegin();
    };
    
    auto end(){
        return data.end();
    };
    
    auto cend(){
        return data.cend();
    };
};

#endif //_ENUMARRAY_H